package org.googlecode.hltwsample.single;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

import org.googlecode.hltw.single.config.server.SingleAppServerNature;
import org.googlecode.hltw.single.config.server.rt.ResponseTimeFunction;
import org.googlecode.hltw.single.config.server.rt.TypicalRtFunction;
import org.googlecode.hltw.single.formula.SingleAppVisitFormula;
import org.googlecode.hltw.single.result.SingleAppVisitResult;
import org.googlecode.hltw.util.math.function.SingleVariableFunction;

/**
 * 
 * @author chenjianjx
 * 
 */
public class CurveMain {

	public static void main(String[] args) {
		List<SingleAppVisitResult> resultsNoProtect = getResults(10, Integer.MAX_VALUE);
		List<SingleAppVisitResult> resultsSimple = getResults(10, 10);
		List<SingleAppVisitResult> resultsComplicate = getResults(10, 20);

		pn("=============csvNoProtect================");
		pn(toCsv(resultsNoProtect));
		pn("=============csvSimpleProtect================");
		pn(toCsv(resultsSimple));
		pn("=============csvComplicateProtect================");
		pn(toCsv(resultsComplicate));

		pn("==============csvCompare=================================");

		pn(getCsvToCompare(resultsNoProtect, resultsSimple, resultsComplicate));

	}

	private static StringBuffer getCsvToCompare(List<SingleAppVisitResult> resultsNoProtect, List<SingleAppVisitResult> resultsSimple, List<SingleAppVisitResult> resultsComplicate) {
		StringBuffer csv = new StringBuffer();
		addCsvElementAtRowBegin(csv, "concurrency");

		addCsvElementAtRowMiddle(csv, "noProtect-ResponseMilisAvg");
		addCsvElementAtRowMiddle(csv, "noProtect-WaitMilisAvg");
		addCsvElementAtRowMiddle(csv, "noProtect-Qps");

		addCsvElementAtRowMiddle(csv, "simple-ResponseMilisAvg");
		addCsvElementAtRowMiddle(csv, "simple-WaitMilisAvg");
		addCsvElementAtRowMiddle(csv, "simple-Qps");

		addCsvElementAtRowMiddle(csv, "complicate-ResponseMilisAvg");
		addCsvElementAtRowMiddle(csv, "complicate-WaitMilisAvg");
		addCsvElementAtRowEnd(csv, "complicate-Qps");

		for (int i = 0; i < resultsNoProtect.size(); i++) {
			SingleAppVisitResult resultNoProtect = resultsNoProtect.get(i);
			SingleAppVisitResult resultSimple = resultsSimple.get(i);
			SingleAppVisitResult resultComplicate = resultsComplicate.get(i);
			addCsvElementAtRowBegin(csv, resultNoProtect.getRequestCount());

			addCsvElementAtRowMiddle(csv, resultNoProtect.getResponseMilisAvg());
			addCsvElementAtRowMiddle(csv, resultNoProtect.getWaitMilisAvg());
			addCsvElementAtRowMiddle(csv, resultNoProtect.getQps());

			addCsvElementAtRowMiddle(csv, resultSimple.getResponseMilisAvg());
			addCsvElementAtRowMiddle(csv, resultSimple.getWaitMilisAvg());
			addCsvElementAtRowMiddle(csv, resultSimple.getQps());

			addCsvElementAtRowMiddle(csv, resultComplicate.getResponseMilisAvg());
			addCsvElementAtRowMiddle(csv, resultComplicate.getWaitMilisAvg());
			addCsvElementAtRowEnd(csv, resultComplicate.getQps());

		}
		return csv;
	}

	private static void pn(Object str) {
		System.out.println(str);
	}

	private static List<SingleAppVisitResult> getResults(int maxThreadHealthy, int maxThreadExtreme) {
		SingleAppServerNature serverNature = new SingleAppServerNature(maxThreadHealthy, maxThreadExtreme);
		ResponseTimeFunction responseTimeFunction = new TypicalRtFunction(BigDecimal.valueOf(10), new SingleVariableFunction() {

			public BigDecimal getValue(BigDecimal concurrencyBigdecimal) {
				int concurrency = concurrencyBigdecimal.intValue();
				double time = -1l;
				if (concurrency <= 20) {
					time = 10 + (double) concurrency / 10;
				} else {
					time = 10 * concurrency;
				}

				return BigDecimal.valueOf(time);
			}
		});
		serverNature.setResponseTimeFunction(responseTimeFunction);

		List<SingleAppVisitResult> results = new ArrayList<SingleAppVisitResult>();
		for (int i = 1; i <= 100; i++) {
			SingleAppVisitResult result = new SingleAppVisitFormula().calculate(serverNature, i);
			results.add(result);

		}
		return results;
	}

	private static String toCsv(List<SingleAppVisitResult> results) {
		StringBuffer csv = new StringBuffer();
		addCsvElementAtRowBegin(csv, "concurrency");
		addCsvElementAtRowMiddle(csv, "serverResponseAvg");
		addCsvElementAtRowMiddle(csv, "serverQps");
		addCsvElementAtRowMiddle(csv, "clientWaitResponseAvg");
		addCsvElementAtRowEnd(csv, "clientQps");

		for (SingleAppVisitResult result : results) {

			addCsvElementAtRowBegin(csv, result.getRequestCount());
			addCsvElementAtRowMiddle(csv, result.getResponseMilisAvg());
			addCsvElementAtRowMiddle(csv, result.getQps());
			addCsvElementAtRowMiddle(csv, result.getWaitMilisAvg());
			addCsvElementAtRowEnd(csv, result.getQps());
		}
		return csv.toString();
	}

	private static void addCsvElementAtRowEnd(StringBuffer csv, Object v) {
		csv.append(",");
		addCsvElement(csv, v);
		csv.append("\n");

	}

	private static void addCsvElementAtRowBegin(StringBuffer csv, Object v) {
		addCsvElement(csv, v);
	}

	private static void addCsvElementAtRowMiddle(StringBuffer csv, Object v) {
		csv.append(",");
		addCsvElement(csv, v);
	}

	private static void addCsvElement(StringBuffer csv, Object v) {

		csv.append("\"");
		csv.append(v);
		csv.append("\"");

	}

}
